import { ref, onMounted, onUnmounted, reactive, toRefs } from 'vue'

export const selectDragFn = ({ fileData = [] }) => {
    const isMouseDown = ref(false)
    const isDragMouseDown = ref(false)
    const fileItems = ref(JSON.parse(JSON.stringify(fileData)))
    const selectedData = ref([])
    const dragItems = ref([])

    const fileContainerMainRef = ref(null)
    const fileContainer = ref(null)
    const drawSelectAreaRef = ref(null)
    const fileDraggingWrapRef = ref(null)

    const mouse = reactive({
        startTop: 0,
        startLeft: 0,
        endTop: 0,
        endLeft: 0,
        parentLeft: 0,
        parentTop: 0
    })
    const { startLeft, startTop, endLeft, endTop, parentLeft, parentTop } = toRefs(mouse)

    const onMouseDown = (evt) => {
        evt.preventDefault()
        evt.stopPropagation()
        // 鼠标按下触发，先清空数据
        selectedData.value = []
        dragItems.value = []

        // 父元素不存在就返回false
        if (!fileContainer.value) return false

        // 重新获取容器，如果容器有新增子元素的话
        fileContainer.value = document.querySelector('.file-container')

        isMouseDown.value = true
        const { left, top } = fileContainer.value.getBoundingClientRect()
        parentLeft.value = left
        parentTop.value = top

        startLeft.value = evt.clientX - left
        startTop.value = evt.clientY - top

        document.addEventListener('mousemove', onMouseMove)
        document.addEventListener('mouseup', onMouseUp)
    }

    const onMouseMove = (evt) => {
        if (isMouseDown.value) {
            endLeft.value = evt.clientX -  parentLeft.value;
            endTop.value = evt.clientY - parentTop.value;

            // 鼠标移动时触发，先清空数据
            selectedData.value = []
            dragItems.value = []

            // 设置遮罩层的位置
            const maskTop = Math.min(startTop.value, endTop.value);
            const maskLeft = Math.min(startLeft.value, endLeft.value);

            // 计算遮罩层宽高
            const maskWidth = Math.abs(startLeft.value - endLeft.value);
            const maskHeight = Math.abs(startTop.value - endTop.value);

            styleVars({
                mx1: maskLeft,
                my1: maskTop,
                maskW: maskWidth,
                maskH: maskHeight,
                opacity: 1,
                useSelect: 'none',
                selecteDisplay: 'block'
            })

            // 设置选中元素的样式
            selectedItem()
        }
    }

    const onMouseUp = (evt) => {
        isMouseDown.value = false
        styleVars({
            opacity: 0,
            useSelect: ''
        })
        // 清除选区宽高
        setTimeout(() => {
            styleVars({
                mx1: -999,
                my1: -999,
                maskW: 0,
                maskH: 0,
                selecteDisplay: 'none'
            })
        }, 300)
        document.onmousedown = null
        document.onmousemove = null
    }

    // 配置选中元素
    const selectedItem = () => {
        if (!drawSelectAreaRef.value) return 

        const rect = drawSelectAreaRef.value.getBoundingClientRect()
        const children = Array.from(fileContainer.value.children).filter(el => !['file-dragging-wrap','draw-selection'].includes(el.className))
        
        for (let i = 0; i < children.length; i++) {
            const child = children[i];
            const { left, top, right, bottom } = child.getBoundingClientRect()

            const dataFlipKey = child.getAttribute('data-flip-key')
            
            // 判断子元素和遮罩是否有重叠
            if (
                right > rect.left &&
                bottom > rect.top &&
                left < rect.right &&
                top < rect.bottom
            ) {
                child.classList.remove('hover')
                child.classList.add('select')
                selectedData.value.push({
                    index: i,
                    key: dataFlipKey
                })
        
                dragItems.value.push(fileItems.value[i])
                // console.log('selectedData：', selectedData.value);
            } else {
                child.classList.remove('select')
            }
        }
    }

    // 单个元素鼠标按下事件
    const onItemMouseDown = (evt, item, index) => {
        if (!fileDraggingWrapRef.value) return false

        isDragMouseDown.value = true
        // 判断当前元素是否被选中，如果选中了，就不能绘制选区，否则可以绘制选区
        if (selectedData.value.some(e => e.index === index)) {
            evt.preventDefault()
            evt.stopPropagation()

            // console.log(item, index, selectedData.value);
            const { left, top } = fileContainer.value.getBoundingClientRect()
            parentLeft.value = left
            parentTop.value = top

            // 拖拽当前选中元素，监听鼠标拖拽事件
            document.addEventListener('mousemove', onMouseDragMove)
            document.addEventListener('mouseup', onMouseDragUp)
        }
    }

    const onMouseDragMove = (evt) => {
        if (isDragMouseDown.value && !isMouseDown.value) {
            let dragX = evt.clientX - parentLeft.value
            let dragY = evt.clientY - parentTop.value
            if (fileDraggingWrapRef.value) {
                const { width: PW, height: PH } = fileContainer.value.getBoundingClientRect()
                const { width, height } = fileDraggingWrapRef.value.getBoundingClientRect()
                const w_ = PW  - width
                const h_ = PH - height

                // 不能溢出父元素
                dragX = Math.min(Math.max(0, dragX), w_)
                dragY = Math.min(Math.max(0, dragY), h_)
                
                fileDraggingWrapRef.value.style.opacity = 1
                fileDraggingWrapRef.value.style.left = `${dragX}px`
                fileDraggingWrapRef.value.style.top = `${dragY}px`
            }
        }
    }

    const onMouseDragUp = (evt) => {
        fileDraggingWrapRef.value.style.opacity = 0
        isDragMouseDown.value = false
        startLeft.value = 0
        startTop.value = 0
        document.onmousedown = null
        document.onmousemove = null
    }

    const styleVars = (vars, el = document.documentElement) => {
        Object.keys(vars).forEach(key => {
            el.style.setProperty(`--${key}`, vars[key]);
        });
    };


    onUnmounted(() => {
        document.removeEventListener('mousemove', onMouseMove)
        document.removeEventListener('mouseup', onMouseUp)
    })

    onMounted(() => {
        fileContainerMainRef.value = document.querySelector('.file-container-main')
        fileContainer.value = document.querySelector('.file-container')
        drawSelectAreaRef.value = document.querySelector('.draw-selection')
        fileDraggingWrapRef.value = document.querySelector('.file-dragging-wrap')
    })

    return {
        selectedData,
        dragItems,
        isDragMouseDown,
        onMouseDown,
        onItemMouseDown
    }
}